﻿using System;
using System.IO;
using System.Management;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Windows;
using Microsoft.TeamFoundation.Client;

namespace TfsGiggle.Configure
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
            int dwLogonType, int dwLogonProvider, out IntPtr phToken);

        public MainWindow()
        {
            InitializeComponent();
        }

        private void btnConfigure_Click(object sender, RoutedEventArgs e)
        {
            if (String.IsNullOrWhiteSpace(tbDomainUserName.Text))
            {
                MessageBox.Show("Please enter domain and username");
                return;
            }

            var userParts = tbDomainUserName.Text.Split('\\');
            if (userParts == null || userParts.Length != 2)
            {
                MessageBox.Show("Please enter domain and username on the form domain\\username");
                return;
            }

            const int LOGON32_PROVIDER_DEFAULT = 0;
            const int LOGON32_LOGON_INTERACTIVE = 2; //This parameter causes LogonUser to create a primary token. 

            IntPtr handle;
            if (!LogonUser(userParts[1], userParts[0], pbPassword.Password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out handle))
            {
                MessageBox.Show("Unable to login as domain\\username with the given password");
                return;
            }

            if (String.IsNullOrWhiteSpace(pbPassword.Password))
            {
                MessageBox.Show("Please enter password");
                return;
            }

            if (String.IsNullOrWhiteSpace(tbTFSUrl.Text))
            {
                MessageBox.Show("Please enter a TFS url");
                return;
            }

            try
            {
                using (var tfs = TfsConfigurationServerFactory.GetConfigurationServer(new Uri(tbTFSUrl.Text)))
                {
                    tfs.EnsureAuthenticated();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return;
            }

            SetTfsUrl(tbTFSUrl.Text);
            SetUserCredentials(tbDomainUserName.Text, pbPassword.Password);

            MessageBox.Show("TfsGiggle is now configured, start checking in source code and start the searching!");
            this.Close();

        }

        private void SetTfsUrl(string tfsUrl)
        {
            const string configName = "TfsGiggle.EngineService.exe.config";
            try
            {
                var content = File.ReadAllText(configName);
                if (File.Exists(configName + ".bak"))
                {
                    File.Delete(configName + ".bak");
                }
                File.WriteAllText(configName + ".bak", content);
                var re = new Regex("add key=\"TfsUrl\" value=\"[\\w:/]+\"");
                var updatedContent = re.Replace(content, "add key=\"TfsUrl\" value=\"" + tfsUrl + "\"");
                File.WriteAllText(configName, updatedContent);
            }
            catch (Exception ex)
            {
                MessageBox.Show("SetTfsUrl:" + ex.ToString());
            }
        }

        private void SetUserCredentials(string userName, string password)
        {
            var serviceName = "Win32_Service.Name='TfsGiggleService'";
            var managementObject = new ManagementObject(serviceName);
            var result = managementObject.InvokeMethod("Change", new object[] { null, null, null, null, null, null, userName, password, null, null, null });
            string errorMessage;
            if (myUtils.LSAUtility.SetRight(userName, "SeServiceLogonRight", out errorMessage) > 0)
            {
                MessageBox.Show(errorMessage);
            }
            else
            {
                result = managementObject.InvokeMethod("StartService", new object[] { null });
            }
        }

        private void tbDomainUserName_Loaded(object sender, RoutedEventArgs e)
        {
            tbDomainUserName.Text = Environment.UserDomainName + "\\" + Environment.UserName;
        }

        private void pbPassword_Loaded(object sender, RoutedEventArgs e)
        {
            pbPassword.Focus();
        }
    }
}